/*
 * Copyright (c) 2011, 张达林
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of SlotBoard nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package cc.gpai.util.slotboard;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import cc.gpai.data_stru.multimap.MultiMap;
import cc.gpai.data_stru.multimap.impl.WeakListMultiMap;



@SuppressWarnings("rawtypes")
public class SlotBoard {

	private static final MultiMap<String, String> board = new WeakListMultiMap<String,String>();
	private static final MultiMap<String, Slot> slot_map = new WeakListMultiMap<String,Slot>();
	public static final Random rand = new Random();
	public static void addSlot(Slot slot){
		slot_map.put(slot.getName(), slot);
	}
	public static void removeSlot(Slot slot){
		slot_map.remove(slot.getName(), slot);
		slot_map.removeValue(slot);
	}
	public static void connect(String signal,String slot){
		board.put(signal, slot);
	}
	public static void disconnect(String signal,String slot){
		board.remove(signal, slot);
	}
	public static void connect(Signal signal,Slot slot){
		addSlot(slot);
		connect(signal.getName(), slot.getName());
	}
	public static void disconnect(Signal signal,Slot slot){
		disconnect(signal.getName(), slot.getName());
	}
	protected static void updateName(String old,String neo,Slot slot){
		if(slot_map.containsKey(old)&&slot_map.containsValue(slot)){
			slot_map.remove(old, slot);
		}
		slot_map.put(neo, slot);
	}
	@SuppressWarnings("unchecked")
	protected static Object deliverSignal(SignalEvent e){
		Collection<String> slot_names = board.getValues(e.signal.getName());
		if(slot_names==null)return null;
		Set<Slot> slots = new HashSet<Slot>();
		for(String str:slot_names){
			Collection<Slot> col_slot=slot_map.getValues(str);
			if(col_slot!=null)
				slots.addAll(col_slot);
		}
		if((e.method.getName().equals("getProperties"))&&(e.method.getParameterTypes().length==1)&&(e.method.getParameterTypes()[0].equals(String.class))){
			Collection<Object> col = new ArrayList<Object>();
			for(Slot slot:slots){
				if(slot==null)continue;
				Object result = slot.receiveSignal(e);
				try{
					col.addAll((Collection<Object>) result);
				}catch(Exception x){
					continue;
				}
			}
			return col;
		}else{
			Object result = null;
			for(Slot slot:slots){
				if(slot==null)continue;
				Object o = slot.receiveSignal(e);
				if(o!=null){
					result=o;
				}
			}
			return result;
		}
	}
}
